# -*- coding: utf-8 -*-
#
from collections import defaultdict

from django.db.models import Count, Q, F, Value
from django.db.models.functions import Concat
from django.http import JsonResponse
from rest_framework.views import APIView

from accounts.const import Source
from accounts.models import Account, AccountTemplate
from assets.const import Connectivity
from common.permissions import IsValidLicense
from common.utils import lazyproperty
from rbac.permissions import RBACPermission
from reports.api.assets.base import group_stats
from reports.mixins import DateRangeMixin

__all__ = ['AccountStatisticApi']


class AccountStatisticApi(DateRangeMixin, APIView):
    http_method_names = ['get']
    rbac_perms = {
        'GET': 'accounts.view_account',
    }
    permission_classes = [RBACPermission, IsValidLicense]

    @lazyproperty
    def base_qs(self):
        return Account.objects.all()

    @lazyproperty
    def template_qs(self):
        return AccountTemplate.objects.all()

    def get_change_secret_account_metrics(self):
        filtered_queryset = self.filter_by_date_range(self.base_qs, 'date_change_secret')

        data = defaultdict(set)
        for t, _id in filtered_queryset.values_list('date_change_secret', 'id'):
            date_str = str(t.date())
            data[date_str].add(_id)

        metrics = [len(data.get(str(d), set())) for d in self.date_range_list]
        return metrics

    def get(self, request, *args, **kwargs):
        qs = self.base_qs

        stats = qs.aggregate(
            total=Count(1),
            active=Count(1, filter=Q(is_active=True)),
            connected=Count(1, filter=Q(connectivity=Connectivity.OK)),
            su_from=Count(1, filter=Q(su_from__isnull=False)),
            date_change_secret=Count(1, filter=Q(secret_reset=True)),
        )

        stats['template_total'] = self.template_qs.count()

        source_pie_data = [
            {'name': str(Source(source).label), 'value': total}
            for source, total in
            qs.values('source').annotate(
                total=Count(1)
            ).values_list('source', 'total')
        ]

        by_connectivity = group_stats(
            qs, 'label', 'connectivity', Connectivity.as_dict(),
        )

        top_assets = qs.values('asset__name') \
                         .annotate(account_count=Count('id')) \
                         .order_by('-account_count')[:10]

        top_version_accounts = qs.annotate(
            display_key=Concat(
                F('asset__name'),
                Value('（'),
                F('username'),
                Value('）')
            )
        ).values('display_key', 'version').order_by('-version')[:10]

        payload = {
            'account_stats': stats,
            'top_assets': list(top_assets),
            'top_version_accounts': list(top_version_accounts),
            'source_pie': source_pie_data,
            'by_connectivity': by_connectivity,
            'change_secret_account_metrics': {
                'dates_metrics_date': self.dates_metrics_date,
                'dates_metrics_total': self.get_change_secret_account_metrics(),
            }
        }
        return JsonResponse(payload, status=200)
